﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common.Net.DataStructures
{
    /// <summary>
    /// See nested classes for details
    /// </summary>
    public abstract class FunctionCallResult
    {
        public abstract object ReturnValue { get; }
        public abstract Exception ThrownException { get; }

        sealed class ReturnedVariant : FunctionCallResult
        {
            readonly object _returnValue;

            public ReturnedVariant(object returnValue)
            {
                _returnValue = returnValue;
            }

            public sealed override object ReturnValue
            {
                get { return _returnValue; }
            }

            public sealed override Exception ThrownException
            {
                get { throw new NotSupportedException("Function returned value"); }
            }
        }

        sealed class ThrewVariant : FunctionCallResult
        {
            readonly Exception _thrownException;

            public ThrewVariant(Exception thrownException)
            {
                _thrownException = thrownException;
            }

            public override object ReturnValue
            {
                get { throw new NotSupportedException("Function threw exception"); }
            }

            public override Exception ThrownException
            {
                get { return _thrownException; }
            }
        }

        public bool DidNotThrow
        {
            get { return !(this is ThrewVariant); }
        }            

        public static FunctionCallResult Get(Func<object> func)
        {
            try
            {
                return new FunctionCallResult.ReturnedVariant(func());
            }
            catch (Exception ex)
            {
                return new FunctionCallResult.ThrewVariant(ex);
            }
        }
    }
}
